from fastapi import APIRouter, HTTPException, BackgroundTasks, Query
from fastapi.responses import StreamingResponse
from typing import List
import asyncio
import logging
from datetime import datetime
import httpx
import re

from api.models.video_models import (
    ParseVideoRequest, 
    BatchParseRequest, 
    VideoInfo, 
    ApiResponse, 
    ErrorResponse,
    HealthResponse,
    PlatformInfo
)
from core.video_service import VideoService
from utils.platform_detector import PlatformDetector

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1", tags=["video"])

# 初始化服务
video_service = VideoService()
platform_detector = PlatformDetector()


@router.post("/parse/video", response_model=VideoInfo, summary="解析单个视频")
async def parse_single_video(request: ParseVideoRequest):
    """
    解析单个视频链接
    
    - **url**: 视频链接
    - **platform**: 平台类型 (douyin, tiktok, bilibili, auto)
    """
    try:
        logger.info(f"解析视频: {request.url}")
        
        # 如果是自动检测，先识别平台
        if request.platform == "auto":
            detected_platform = platform_detector.detect_platform(request.url)
            if not detected_platform:
                raise HTTPException(
                    status_code=400, 
                    detail="无法识别视频平台，请手动指定platform参数"
                )
            request.platform = detected_platform
        
        # 调用相应的爬虫服务解析视频
        video_info = await video_service.parse_video(request.url, request.platform)
        
        if not video_info:
            raise HTTPException(
                status_code=404,
                detail="视频解析失败，请检查链接是否有效"
            )
        
        logger.info(f"视频解析成功: {video_info.title}")
        return video_info
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"视频解析异常: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail=f"服务器内部错误: {str(e)}"
        )


@router.post("/parse/batch", response_model=List[VideoInfo], summary="批量解析视频")
async def parse_batch_videos(request: BatchParseRequest):
    """
    批量解析视频链接
    
    - **urls**: 视频链接列表 (最多10个)
    - **platform**: 平台类型 (如果是auto，会自动检测每个链接的平台)
    """
    try:
        if len(request.urls) > 10:
            raise HTTPException(
                status_code=400,
                detail="批量解析最多支持10个链接"
            )
        
        logger.info(f"批量解析视频: {len(request.urls)}个链接")
        
        # 创建解析任务
        tasks = []
        for url in request.urls:
            # 检测平台
            platform = request.platform
            if platform == "auto":
                platform = platform_detector.detect_platform(url)
                if not platform:
                    logger.warning(f"无法识别平台，跳过链接: {url}")
                    continue
            
            # 创建异步任务
            task = video_service.parse_video(url, platform)
            tasks.append(task)
        
        # 并发执行解析任务
        results = await asyncio.gather(*tasks, return_exceptions=True)
        
        # 过滤成功的结果
        video_list = []
        for i, result in enumerate(results):
            if isinstance(result, Exception):
                logger.error(f"解析失败 {request.urls[i]}: {str(result)}")
            elif result:
                video_list.append(result)
        
        logger.info(f"批量解析完成: 成功{len(video_list)}个，失败{len(results)-len(video_list)}个")
        return video_list
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"批量解析异常: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail=f"服务器内部错误: {str(e)}"
        )


@router.get("/platforms", response_model=List[PlatformInfo], summary="获取支持的平台")
async def get_supported_platforms():
    """
    获取所有支持的视频平台列表
    """
    platforms = [
        PlatformInfo(
            name="抖音",
            code="douyin", 
            enabled=True,
            description="抖音短视频平台"
        ),
        PlatformInfo(
            name="TikTok",
            code="tiktok",
            enabled=True, 
            description="TikTok国际版短视频平台"
        ),
        PlatformInfo(
            name="哔哩哔哩",
            code="bilibili",
            enabled=True,
            description="哔哩哔哩弹幕视频网"
        )
    ]
    return platforms


@router.get("/health", response_model=HealthResponse, summary="健康检查")
async def health_check():
    """
    服务健康检查
    """
    return HealthResponse(
        status="ok",
        service="python-crawler",
        version="1.0.0",
        timestamp=datetime.now().isoformat()
    )


@router.get("/stats", summary="获取服务统计")
async def get_service_stats():
    """
    获取服务统计信息
    """
    stats = await video_service.get_stats()
    return {
        "total_parsed": stats.get("total_parsed", 0),
        "success_rate": stats.get("success_rate", 0.0),
        "avg_parse_time": stats.get("avg_parse_time", 0.0),
        "supported_platforms": len(await get_supported_platforms())
    }


@router.get("/download", summary="下载视频")
async def download_video(
    url: str = Query(..., description="视频URL"),
    with_watermark: bool = Query(False, description="是否包含水印"),
    prefix: bool = Query(True, description="是否添加前缀")
):
    """
    通过API代理下载视频文件
    
    - **url**: 视频链接
    - **with_watermark**: 是否包含水印
    - **prefix**: 是否添加文件名前缀
    """
    try:
        logger.info(f"开始下载视频: {url}")
        
        # 首先解析视频获取真实下载链接
        detected_platform = platform_detector.detect_platform(url)
        if not detected_platform:
            raise HTTPException(status_code=400, detail="无法识别视频平台")
        
        # 解析视频信息获取下载链接
        video_info = await video_service.parse_video(url, detected_platform)
        if not video_info or not video_info.download_url:
            raise HTTPException(status_code=404, detail="无法获取视频下载链接")
        
        # 从download_url中提取真实的视频URL（如果包含API链接）
        real_video_url = video_info.download_url
        if "api/download?url=" in real_video_url:
            # 从API URL中提取真实URL
            match = re.search(r'url=([^&]+)', real_video_url)
            if match:
                import urllib.parse
                real_video_url = urllib.parse.unquote(match.group(1))
        
        # 构建文件名 - 保留中文但处理特殊字符
        safe_title = video_info.title or 'video'
        safe_author = video_info.author or 'author'
        
        # 只移除文件系统不支持的特殊字符，保留中文
        safe_title = re.sub(r'[<>:"/\\|?*]', '_', safe_title)[:50]
        safe_author = re.sub(r'[<>:"/\\|?*]', '_', safe_author)[:20]
        
        # 移除控制字符但保留中文
        safe_title = re.sub(r'[\x00-\x1f\x7f]', '', safe_title)
        safe_author = re.sub(r'[\x00-\x1f\x7f]', '', safe_author)
        
        filename = f"{safe_title}_{video_info.id}.mp4"
        if prefix:
            filename = f"[{safe_author}]_{filename}"
        
        # 处理多余的空格和点
        filename = re.sub(r'\s+', ' ', filename).strip()
        filename = re.sub(r'\.+$', '', filename)  # 移除结尾的点
        if not filename.endswith('.mp4'):
            filename += '.mp4'
        
        # 使用httpx代理下载
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Referer": url,
            "Accept": "*/*"
        }
        
        async with httpx.AsyncClient(timeout=60.0) as client:
            response = await client.get(real_video_url, headers=headers)
            response.raise_for_status()
            
            # 获取内容类型
            content_type = response.headers.get("content-type", "video/mp4")
            
            # 返回流式响应
            # 为了最大兼容性，同时提供ASCII和UTF-8文件名
            import urllib.parse
            
            # ASCII fallback文件名
            ascii_filename = re.sub(r'[^\x00-\x7F]', '_', filename)
            # URL编码的UTF-8文件名
            encoded_filename = urllib.parse.quote(filename)
            
            return StreamingResponse(
                iter([response.content]),
                media_type=content_type,
                headers={
                    "Content-Disposition": f"attachment; filename=\"{ascii_filename}\"; filename*=UTF-8''{encoded_filename}",
                    "Content-Length": str(len(response.content)),
                    "Cache-Control": "no-cache"
                }
            )
            
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"下载视频失败: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail=f"下载失败: {str(e)}"
        )